package promote.brozen.algorithm.tree.balance.bpt;

import lombok.Data;

/**
 * @author Brozen
 * @date 2020/1/17 5:21 PM
 */
@Data
public class BPlusTreeNode<K extends Comparable<K>> {

    private BPlusTreeChildChainNode<K> parent;

    private BPlusTreeChildChainNode<K> head;

    private BPlusTreeChildChainNode<K> tail;

    private int keySize;

    private boolean isLeaf;

    private BPlusTreeNode<K> next;

    public BPlusTreeNode() {
        this(null);
    }

    public BPlusTreeNode(K key) {
        this.head = new BPlusTreeChildChainNode<>(this);
        this.tail = new BPlusTreeChildChainNode<>(this);
        this.isLeaf = true;

        if (key != null) {
            BPlusTreeDataChainNode<K> dataChainNode = new BPlusTreeDataChainNode<>(this, key);
            this.head.setNext(dataChainNode);
            dataChainNode.setPrev(this.head);
            this.tail.setPrev(dataChainNode);
            dataChainNode.setNext(this.tail);
            this.keySize = 1;
        }
    }

    public BPlusTreeDataChainNode<K> getDataChainNode(int i) {
        BPlusTreeDataChainNode<K> dataChainNode = this.head.getNext();
        int counter = 0;
        while (dataChainNode != null) {
            if (i == counter) {
                return dataChainNode;
            }

            counter++;
            dataChainNode = dataChainNode.getNext().getNext();
        }

        throw new ArrayIndexOutOfBoundsException("BTreeNode chain don't have a data chain node at "
                + i + ". Max key size is " + keySize);
    }

    public void increaseKeySize() {
        this.keySize++;
    }

    public void decreaseKeySize() {
        this.keySize--;
    }

    @Override
    public String toString() {
        StringBuilder str = new StringBuilder("BTreeNode[size=").append(keySize).append(", chain=[");
        BPlusTreeChildChainNode node = this.head;
        do {
            str.append("[child↓").append(node.toString()).append("] -> ");
            BPlusTreeDataChainNode dataNode = node.getNext();
            if (dataNode != null) {
                str.append("[key=").append(dataNode.getKey()).append("] -> ");
            }
            node = dataNode == null ? null : dataNode.getNext();
        } while (node != null);
        str.append("]]");
        return str.toString();
    }
}
